package com.jiao.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jiao.domain.entity.LikeArticle;
import com.jiao.mapper.LikeArticleMapper;
import com.jiao.utils.RedisKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Component
@EnableScheduling
public class RedisTask {
    @Autowired
    LikeArticleMapper likeArticleMapper;
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    //每天零点进去redis同步到数据库中
    @Scheduled(cron = "0 0 0 * * ?")
    public void execute() {
        log.info("=========Redis缓存数据持久化到数据库中，任务启动============");

        //取出redis中待持久化数据的key值集合
        String pattern = RedisKeyUtil.getPrefixArticleLiker()+"*";
        log.info("key值模板：{}",pattern);
        Set<String> keys = redisTemplate.keys(pattern);
        if(Objects.isNull(keys) || keys.isEmpty()){
            log.info("=========Redis缓存数据持久化到数据库中，redis中无对应key值，任务结束============");
            return;
        }
        log.info("redis的查找满足条件的keys操作，返回值：{}",keys);

        //截取key值集合中的文章id集合
        int length = RedisKeyUtil.getPrefixArticleLiker().length();
        List<Long> collect = keys.stream().map(key ->  Long.parseLong( key.substring(length), 10)) .collect(Collectors.toList());
        log.info("截取key值集合中的文章id集合，返回值：{}",collect);

        //搜出所有的文章id集合的数据
        LambdaQueryWrapper<LikeArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(LikeArticle::getArticleId,collect);
        List<LikeArticle> likeArticles = likeArticleMapper.selectList(queryWrapper);

        //将数据库中的文章数据，以文章id分组存储map中
        Map<Long,Set<Long>> articleUserIdMap = new HashMap<>();
        likeArticles.forEach(likeArticle -> {
            if(articleUserIdMap.containsKey(likeArticle.getArticleId())){
                articleUserIdMap.get(likeArticle.getArticleId()).add(likeArticle.getUserId());
            }else {
                articleUserIdMap.put(likeArticle.getArticleId(), Stream.of(likeArticle.getUserId()).collect(Collectors.toSet()));
            }
        });

        //每篇文章进行两次sql I/O处理
        keys.forEach(key ->{
            // 数据库中的文章id对应的userid集合  A
            Long articleId= Long.parseLong(key.substring(length), 10);
            Set<Long> aIds = articleUserIdMap.get(articleId);
            log.info("数据库中的文章id对应的userid集合，aIds：{}",aIds);
            // redis中的数据  B
            Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
            Set<Long> bIds = entries.keySet().stream().map(keySet -> Long.parseLong( keySet.toString(), 10)).collect(Collectors.toSet());
            log.info("redis中的数据，bIds：{}",bIds);
            // 将A有B没有的数据，从数据库中删除
            List<Long> a_bIds = aIds.stream().filter(id -> !bIds.contains(id)).collect(Collectors.toList());
            log.info("a_bIds：{}",a_bIds);
            if(!a_bIds.isEmpty()){
                LambdaQueryWrapper<LikeArticle> queryWrapper1 = new LambdaQueryWrapper<>();
                queryWrapper1.eq(LikeArticle::getArticleId,articleId).in(LikeArticle::getUserId,a_bIds);
                int delete = likeArticleMapper.delete(queryWrapper1);
                log.info("likeArticleMapper的delete操作，返回值：{}",delete);
            }
            // 将B有A没有的数据，insert到数据库中。 批量插入使用<foreach>标签，循环拼接出values(),()后面的值
            List<Long> b_aIds = bIds.stream().filter(id -> !aIds.contains(id)).collect(Collectors.toList());
            log.info("b_aIds：{}",b_aIds);
            // insert into tb (列名) values (),() ...
            if(!b_aIds.isEmpty()){
                List<LikeArticle> likeArticleList = new LinkedList<>();
                //对于redis存的时间，如果存入LikeArticle对象中，并转变为LocalDateTime类型。
                b_aIds.forEach(id -> likeArticleList.add(new LikeArticle().setArticleId(articleId).setUserId(id)));
                log.info("likeArticleList：{}",likeArticleList);
                Integer integer = likeArticleMapper.insertLikeArticles(likeArticleList);
                log.info("likeArticleMapper的insertLikeArticles操作，返回值：{}",integer);
            }
            redisTemplate.delete(key);
        });

        log.info("=========Redis缓存数据持久化到数据库中，任务结束============");
    }
}
